/*
 *      lcm_func.c
 *      
 *      Copyright 2009 Daniele Ricci <denn86@gmail.com>, Luca Saccagi <luksak86@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */


#include "lcm.h"

#ifndef _LCM_IMPL
#define _LCM_IMPL

#ifdef _WIN32
static void version(int argc, char **argv){
#else
void version(int argc, char **argv){
#endif
	if(argc <= 1) return;
	if(strcmp(argv[1],"-v")==0){ printf(_VERSION1); printf("\n"); exit(0); }
	if(strcmp(argv[1],"-V")==0){ printf(_VERSION); printf("\n"); exit(0); }
	return;
}



#ifdef _WIN32
static void init(void){
#else
void init(void){
#endif
	FILE *group;
	char g[1024];
	groups *cur;
	
	cur_sign=(sign*)malloc(sizeof(sign));
	conf_g=NULL;
	/*MODIF*/if((group=fopen(c0->groups_file,"rt"))==NULL){
		fprintf(stderr,"ERR - No Group file, using any group\n");
	}else{
		fscanf(group,"%s",g);
		cur=NULL;		
		while(!feof(group)){
			cur=(groups *)malloc(sizeof(groups));
			cur->next=conf_g;
			cur->group_name=(char *)calloc(sizeof(char),strlen(g)+1);
			snprintf(cur->group_name,strlen(g)+1,"%s\0",g);
			/*DBG*/DEBUG == DBG_INIT ? printf("DBG - gr:%s\n",cur->group_name) : 0;
			conf_g=cur;
			fscanf(group,"%s",g);
		}
		fclose(group);
	}
	
	/*ADDED*/xmlDTD_init(c0->dtd_sign);

	/*MODIF*/result=xmlHashCreate(c0->max_hash_entry);	
	/*MODIF*/env=xmlHashCreate(c0->max_hash_entry);
	/*MODIF*/react_do=xmlHashCreate(c0->max_hash_entry);
	/*MODIF*/react_undo=xmlHashCreate(c0->max_hash_entry);
	/*MODIF*/var=xmlHashCreate(c0->max_hash_entry);
	xmlHashAddEntry(env,(xmlChar *)"$LAN",LAN);
	xmlHashAddEntry(env,(xmlChar *)"$EXT_NET",EXT_NET);
	filenum=0;
	cur_sign->curstep=-1;
	proceed=false;
	cur_sign->react_group_list=NULL;
	cur_sign->detect_group_list=NULL;
}

#ifdef _WIN32
static void idmp_connection(VortexConnection *cn,VortexChannel *ch,VortexAsyncQueue *queue){
#else
void idmp_connection(VortexConnection *cn,VortexChannel *ch,VortexAsyncQueue *queue){
#endif
	if(!vortex_sasl_is_enabled()){									//1: check if SASL is activated
		printf("ERR - Unable to initialize SASL profiles.\n");
		exit(-1);
	}
	if(!vortex_connection_is_ok(cn,false)){
		fprintf(stderr,"ERR - Unable to connect remote server, error was: %s\n",vortex_connection_get_message(cn));
		vortex_connection_close(cn);
		vortex_exit();
		exit(-1);
	}
	if(!vortex_connection_is_tlsficated(cn)){
		fprintf(stderr,"ERR - Unable to use TLS profile\n");
		exit(-1);
	}
}

#ifdef _WIN32
static void vortex_error(VortexConnection *cn,VortexChannel *ch){
#else
void vortex_error(VortexConnection *cn,VortexChannel *ch){
#endif

	if(ch==NULL){
		perror("ERR - Unable to create the channel..\n");
		vortex_connection_close(cn);
		vortex_exit();
		exit(-1);
	}
}


#ifdef _WIN32
static char *sasl_get_data(char *item){
#else
char *sasl_get_data(char *item){
#endif
	if(item[0]=='i' && item[1]=='d'){
		//return "bob";
		/*MODIF*/return c0->usr;
	}else if(item[0]=='p' && item[1]=='w'){
		//return "secret";
		/*MODIF*/return c0->pw;
	}else{
		fprintf(stderr,"ERR - Wrong SASL authentication parameter requested:%s\n",item);
		exit(-1);
	}
}

#ifdef _WIN32
static void sasl_verify(VortexConnection *cn){
#else
void sasl_verify(VortexConnection *cn){
#endif
	if(!vortex_sasl_is_authenticated(cn)){
		fprintf(stderr,"ERR - SASL negotiation BAD, unauthenticated user %s\n",vortex_sasl_get_propertie(cn, VORTEX_SASL_AUTH_ID));
		vortex_connection_close(cn);
		vortex_exit();
		exit(-1);
	}else{
		/*DBG*/DEBUG != DAEMON ? printf("SASL negotiation OK, user %s is authenticated\n",vortex_sasl_get_propertie(cn, VORTEX_SASL_AUTH_ID)) : 0;
	}	
}

#ifdef _WIN32
static xmlDocPtr sign_dir_polling(const char *dirname,char *filename){	
#else
xmlDocPtr sign_dir_polling(const char *dirname,char *filename){	
#endif
	char *filename_full;
	int len;
	xmlDocPtr doc;
	
	len=strlen(filename);
	filename_full=(char *)calloc(sizeof(char),strlen(dirname)+len+1);
	strncat(filename_full,dirname,strlen(dirname));
	strncat(filename_full,filename,len);
	doc=NULL;
	if((doc=xmlParseFile(filename_full))!=NULL){
		//if(!(xmlDoc_validate(doc,(const char *)SIGN_DTD))){
		/*MODIF*/if(!(xmlDoc_validate(doc))){
			fprintf(stderr,"Wrong signature, see the sign DTD\n");
			/*ADDED*/free(filename_full);
			/*ADDED*/xmlFreeDoc(doc);
			return NULL;
		}else{
			/*ADDED*/free(filename_full);
			return doc;
		}
	} 
	free(filename_full);
	return NULL;
}

#ifdef _WIN32
static void HashCreate(void *payload,void *data,xmlChar *name){
#else
void HashCreate(void *payload,void *data,xmlChar *name){
#endif
	xmlHashTablePtr hash;
	/*MODIF*/hash=xmlHashCreate(c0->max_hash_entry);
	xmlHashAddEntry(result,(xmlChar *)payload,hash);
	hash=NULL;
}
	

/*NOTA: la hash deallocate sulla result non so se fa la free di tutto in questo
modo, ho provato a modificarla nelle righe indicate con MODIF qui di seguito, 
in modo da provare a richiamare prima una hashscan che richiama hash_deallocate 
e poi fare una xmlhashfree classica, ma cora. ora comunque la situazione è
buona.*/
#ifdef _WIN32
static void hash_deallocate(void *payload,xmlChar* name){
/*MODIF*///static void hash_deallocate(void *payload,void *data,xmlChar* name){
#else
void hash_deallocate(void *payload,xmlChar* name){
/*MODIF*///void hash_deallocate(void *payload,void *data,xmlChar* name){
#endif
	//xmlHashFree((xmlHashTablePtr)payload,NULL);
	/*MODIF*/xmlHashFree((xmlHashTablePtr)payload,hash_free);
}

#ifdef _WIN32
static void hash_free(void *payload,xmlChar* name){
#else
void hash_free(void *payload,xmlChar* name){
#endif
	free(payload);
	return;
}


#ifdef _WIN32
static void free_hash_tables(void){	
#else
void free_hash_tables(void){	
#endif
	//xmlHashFree(react_do,NULL);
	//xmlHashFree(react_undo,NULL);
	//xmlHashFree(var,NULL);
	/*MODIF*/xmlHashFree(react_do,hash_free);
	/*MODIF*/xmlHashFree(react_undo,hash_free);
	/*MODIF*/xmlHashFree(var,hash_free);

	/*MODIF*/react_do=xmlHashCreate(c0->max_hash_entry);
	/*MODIF*/react_undo=xmlHashCreate(c0->max_hash_entry);
	/*MODIF*/var=xmlHashCreate(c0->max_hash_entry);
}


#ifdef _WIN32
static void xmlDTD_init(const char *dtd){
#else
void xmlDTD_init(const char *dtd){
#endif

	xmlInitMemory();
	vctxt=malloc(sizeof(xmlValidCtxt));
	if(vctxt==NULL){
		fprintf(stderr,"ERR - vctxt malloc fail!\n");
		return;
	}
	vctxt->userData=(void *)stderr;
	vctxt->error=(xmlValidityErrorFunc)fprintf;
	vctxt->warning=(xmlValidityWarningFunc)fprintf;
	pdtd=xmlParseDTD(NULL,(xmlChar*)dtd);
	if(pdtd==NULL){
		fprintf(stderr,"ERR - Problem parsing the DTD\n");
		return;
	}
	pdtd->name=xmlStrdup((xmlChar*)dtd);
}

#ifdef _WIN32
//static bool xmlDoc_validate(xmlDocPtr doc,const char *dtd){
/*MODIF*/static bool xmlDoc_validate(xmlDocPtr doc){
#else
//bool xmlDoc_validate(xmlDocPtr doc,const char *dtd){
/*MODIF*/bool xmlDoc_validate(xmlDocPtr doc){
#endif
	/*MOVED*///xmlValidCtxtPtr vctxt;
	/*MOVED*///xmlDtdPtr pdtd;
	
	/*MOVED*///xmlInitMemory();
	/*MOVED*///vctxt=malloc(sizeof(xmlValidCtxt));
	/*MOVED*///if(vctxt==NULL){
		/*MOVED*///fprintf(stderr,"vctxt malloc fail!\n");
		/*MOVED*///return false;
	/*MOVED*///}
	/*MOVED*///vctxt->userData=(void *)stderr;
	/*MOVED*///vctxt->error=(xmlValidityErrorFunc)fprintf;
	/*MOVED*///vctxt->warning=(xmlValidityWarningFunc)fprintf;
	/*MOVED*///pdtd=xmlParseDTD(NULL,(xmlChar*)dtd);
	/*MOVED*///if(pdtd==NULL){
		/*MOVED*///fprintf(stderr,"Problem parsing the DTD\n");
		/*MOVED*///return false;
	/*MOVED*///}
	/*MOVED*///pdtd->name=xmlStrdup((xmlChar*)dtd);
	if(doc==NULL){
		fprintf(stderr,"ERR - Document not parsed successfully.\n\n");
		return false;
	}
	if(!xmlValidateDtd(vctxt,doc,pdtd)){
		xmlFreeDoc(doc);
		return false;
	}
    return true;                  
}

#ifdef _WIN32
static int sign_get_data(xmlDocPtr doc){
#else
int sign_get_data(xmlDocPtr doc){
#endif
	xmlXPathContextPtr xpathCtx; 
    xmlXPathObjectPtr xpathObj;
	char xpath[1024];
	int len,i;
	bool found=false;
	groups *tmp_grouplist,*cur_g;
	/*ADDED*/int sign_id=0;

	
	proceed=false;
	xpathCtx = xmlXPathNewContext(doc);
	if(xpathCtx == NULL) {
		fprintf(stderr,"ERR - unable to create new XPath context\n");
		xmlFreeDoc(doc); 
		return -1;
	}	
	/******************************************************************/
	/** Getting cur_step											 **/
	/******************************************************************/
	if(cur_sign->curstep==-1){
		if((xpathObj = xmlXPathEvalExpression((xmlChar *)"/signature/@cur_step", xpathCtx))== NULL){
			fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
			xmlXPathFreeContext(xpathCtx);  
			return -1;
		}
		sscanf((char *)xpathObj->nodesetval->nodeTab[0]->children->content,"%d",&(cur_sign->curstep));
		xmlXPathFreeObject(xpathObj);
	}
	/******************************************************************/
	/** Getting detect parms from the signature:					 **/
	/** I must load this data to control if at least one group in 	 **/
	/** the signature is present in our configuration list.			 **/
	/** If so, I proceed loading the remaining data, otherwise I	 **/
	/** load the next signature.									 **/
	/******************************************************************/
	cur_g=conf_g;
	while(cur_g!=NULL && found==false){
		sprintf(xpath,"/signature/step[@num=%d]/detect/groups[group=\"%s\"]",cur_sign->curstep,cur_g->group_name);
		if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
			fprintf(stderr,"Error: unable to evaluate xpath expression \n");
			xmlXPathFreeContext(xpathCtx);  
			return -1;
		}
		if((int)xpathObj->nodesetval->nodeNr>0){
			found=true;
		}
		cur_g=cur_g->next;
		xmlXPathFreeObject(xpathObj);
	}
	if(!found){
		/*DBG*/DEBUG == DBG_GROUPS ? printf("DBG - Gruppo non trovato\n") : 0;
		return 1;
	}
	sprintf(xpath,"/signature/step[@num=%d]/detect/groups/group",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	for(i=0;i<(int)xpathObj->nodesetval->nodeNr;i++){
		len=strlen((char *)xpathObj->nodesetval->nodeTab[i]->children->content);
		tmp_grouplist=cur_sign->detect_group_list;
		cur_sign->detect_group_list=(groups *)malloc(sizeof(groups));
		cur_sign->detect_group_list->next=tmp_grouplist;
		cur_sign->detect_group_list->group_name=(char *)calloc(sizeof(char),len+1);
		snprintf(cur_sign->detect_group_list->group_name,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[i]->children->content);
	}
	xmlXPathFreeObject(xpathObj);
	/******************************************************************/
	/** Getting signature params									 **/
	/******************************************************************/
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)"/signature/@id", xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->sig_id=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->sig_id,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	/******************************************************************/
	/** Getting query from the signature							 **/
	/******************************************************************/
	sprintf(xpath,"/signature/step[@num=%d]/detect/query",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->query_string=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->query_string,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	DBG_SIGN_GET_DATA ? printf("DBG - SGD: query_string _%s_\n",cur_sign->query_string) : 0;
	/******************************************************************/
	/** Getting step parms											 **/
	/******************************************************************/
	sprintf(xpath,"/signature/step[@num=%d]/@timeout",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	sscanf((char *)xpathObj->nodesetval->nodeTab[0]->children->content,"%ld",&(cur_sign->timeout));
	xmlXPathFreeObject(xpathObj);
	
	sprintf(xpath,"/signature/step[@num=%d]/@on_timeout",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->on_timeout=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->on_timeout,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	
	sprintf(xpath,"/signature/step[@num=%d]/@severity",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->severity=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->severity,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	
	/******************************************************************/
	/** Getting react parms from the signature						 **/
	/******************************************************************/
	sprintf(xpath,"/signature/step[@num=%d]/react/@undo_time",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	sscanf((char *)xpathObj->nodesetval->nodeTab[0]->children->content,"%d",&(cur_sign->undo_time));
	xmlXPathFreeObject(xpathObj);
	
	sprintf(xpath,"/signature/step[@num=%d]/react/@origin",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->origin=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->origin,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	
	sprintf(xpath,"/signature/step[@num=%d]/react/groups/group",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	for(i=0;i<(int)xpathObj->nodesetval->nodeNr;i++){
		len=strlen((char *)xpathObj->nodesetval->nodeTab[i]->children->content);
		tmp_grouplist=cur_sign->react_group_list;
		cur_sign->react_group_list=(groups *)malloc(sizeof(groups));
		cur_sign->react_group_list->next=tmp_grouplist;
		cur_sign->react_group_list->group_name=(char *)calloc(sizeof(char),len+1);
		snprintf(cur_sign->react_group_list->group_name,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[i]->children->content);
	}
	xmlXPathFreeObject(xpathObj);
	/******************************************************************/
	/** Getting do parms from the signature							 **/
	/******************************************************************/
	sprintf(xpath,"/signature/step[@num=%d]/react/do/@on_fail",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->react_do_on_fail=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->react_do_on_fail,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	
	sprintf(xpath,"/signature/step[@num=%d]/react/do",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->react_do=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->react_do,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	DBG_SIGN_GET_DATA ? printf("DBG - SGD: react_do: _%s_\n",cur_sign->react_do) : 0;
	/******************************************************************/
	/** Getting undo parms from the signature						 **/
	/******************************************************************/
	sprintf(xpath,"/signature/step[@num=%d]/react/undo/@on_fail",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->react_undo_on_fail=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->react_undo_on_fail,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	
	sprintf(xpath,"/signature/step[@num=%d]/react/undo",cur_sign->curstep);
	if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx))== NULL){
		fprintf(stderr,"ERR - unable to evaluate xpath expression \n");
		xmlXPathFreeContext(xpathCtx);  
		return -1;
	}
	len=strlen((char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	cur_sign->react_undo=(char *)calloc(sizeof(char),len+1);
	snprintf(cur_sign->react_undo,len+1,"%s",(char *)xpathObj->nodesetval->nodeTab[0]->children->content);
	xmlXPathFreeObject(xpathObj);
	xmlXPathFreeContext(xpathCtx);
	DBG_SIGN_GET_DATA ? printf("DBG - SGD: react_undo: _%s_\n",cur_sign->react_undo) : 0;
	
	/*ADDED*/sign_id=atoi(cur_sign->sig_id);
	/*ADDED*/query2send=(char *)calloc(sizeof(char),15);
	/*ADDED*/sprintf(query2send,"%03s.%02d select",cur_sign->sig_id,cur_sign->curstep);
	/*DELETED*///query2send=(char *)calloc(sizeof(char),7);
	/*DELETED*///snprintf(query2send,7,"select");
	DBG_SIGN_GET_DATA ? printf("DBG - SGD: end\n") : 0;
	return 0;
}

#ifdef _WIN32
static void sign_handler(VortexChannel *ch,xmlDocPtr doc){	
#else
void sign_handler(VortexChannel *ch,xmlDocPtr doc){	
#endif
	char *delim,*select;
	int sellen;
	
	delim=strstr(cur_sign->query_string," where ");
	sellen=strlen(cur_sign->query_string)-strlen(delim)-6;
	/*MODIF*/select=(char *)calloc(sizeof(char),sellen+1);
	/*DELETED*///snprintf(select,sellen,"%s\0",&cur_sign->query_string[7]);
	/*ADDED*/strncpy(select,&cur_sign->query_string[7],sellen);
	/*DBG*/DEBUG == DBG_SELECT ? printf("DBG - SELECT_%s_\n",select) : 0;
	select_handler(select);
	where_handler(&delim[7]);
	react_handler(cur_sign->react_do,PARSE_DO);
	react_handler(cur_sign->react_undo,PARSE_UNDO);
	//~ xmlHashScan(react_do,hash_print,"f");
	free(select);
}

#ifdef _WIN32
static void select_handler(char *select){
#else
void select_handler(char *select){
#endif
	char *token,*name,*val;
	xmlHashTable *hash;
	/*ADDED*/int q2slen=0;


	/*DBG*/DEBUG == DBG_SELECT_HAN ? printf("DBG - Q2S: _%s_\n",query2send) : 0;
	token=strtok(select,"=");
	while(token!=NULL){
		name=(char *)calloc(sizeof(char),strlen(token)+1);
		/*DELETED*/snprintf(name,strlen(token)+1,token);
		/*ADDED*/strncpy(name,token,strlen(token));
		if((token=strtok(NULL," "))!=NULL){		
			val=(char *)calloc(sizeof(char),strlen(token)+1);
			/*DELETED*///snprintf(val,strlen(token)+1,token);
			/*ADDED*/strncpy(val,token,strlen(token));
			/*DBG*/DEBUG == DBG_SELECT_HAN ? printf("DBG - VAL_%s_\n",val) : 0;
			q2slen=strlen(query2send);
			query2send=(char *)realloc(query2send,strlen(query2send)+strlen(val)+1);
			//strncat(query2send," ",1);
			/*DBG*/DEBUG == DBG_SELECT_HAN ? printf("DBG - Q2SLEN=%d\n",q2slen) : 0;
			query2send[q2slen]=' ';
			query2send[q2slen+1]='\0';
			/*STRNCAT*/strncat(query2send,val,strlen(val));
			//mystrncat(query2send,val,strlen(val));
			/*DBG*/DEBUG == DBG_SELECT_HAN ? printf("DBG - Q2S_%s_\n",query2send) : 0;
			if(xmlHashAddEntry(var,(xmlChar *)name,val)!=0){
				fprintf(stderr,"Failed to insert %s->%s in var table\n",name,val);
				if(xmlHashUpdateEntry(var,(xmlChar *)name,val,NULL)!=0){
					fprintf(stderr,"Update of %s->%s in var table failed\n",name,val);
					exit(-1);
				}
			}
			hash=xmlHashCreate(100);
			xmlHashAddEntry(result,(xmlChar *)val,hash);
			hash=NULL;
			token=strtok(NULL,"=");
		}
	}
	/*DBG*/DEBUG == DBG_SELECT_HAN ? printf("DBG - Q2S_%s_\n",query2send) : 0;
}

#ifdef _WIN32
static void where_handler(char *where){
#else
void where_handler(char *where){
#endif
	char *mywhere,*varname,*varval;
	int i,varindex,varlen,theresavar=0,len,q2slen=0;
	
	mywhere=NULL;
	if(strstr(where,"$")==NULL){
		/*DBG*/DEBUG == DBG_WHERE_HAN ? printf("DBG - WHERE_%s_\n",where) : 0;
		/*MODIF*/mywhere=(char *)calloc(sizeof(char),strlen(where)+8);
		/*MODIF*/snprintf(mywhere,strlen(where)+7,"where %s\0",where);
	}else{
		i=0;
		mywhere=(char *)calloc(sizeof(char),8);
		snprintf(mywhere,8," where ");
		while(where[i]!=';'){
			if(where[i]=='$'){
				varlen=0;
				varindex=i;
				while((where[i]!=' ')&&(where[i]!='|')&&(where[i]!=')')&&(where[i]!=';')){
					varlen++;
					i++;
				}
				varname=(char *)calloc(sizeof(char),varlen+1);
				snprintf(varname,varlen+1,"%s",&where[varindex]);
				varval=xmlHashLookup(env,(xmlChar *)varname);
				len=strlen(mywhere)+strlen(varval)+2;
				mywhere=(char *)realloc(mywhere,(size_t)len);
				/*STRNCAT*/strncat(mywhere,varval,strlen(varval));
				/*STRNCAT*/strncat(mywhere,&where[i],1);
				//mystrncat(mywhere,varval,strlen(varval));
				//mystrncat(mywhere,&where[i],1);
				free(varname);
			}else{
				mywhere=(char *)realloc(mywhere,strlen(mywhere)+1);
				/*STRNCAT*/strncat(mywhere,&where[i],1);
				//mystrncat(mywhere,&where[i],1);
			}
			i++;
		}
		mywhere=(char *)realloc(mywhere,strlen(mywhere)+1);
		/*STRNCAT*///strncat(mywhere,";",1);
		//mystrncat(mywhere,";",1);
		/*ADDED*/strncat(mywhere,";",1);
	}
	q2slen=strlen(query2send);
	query2send=(char *)realloc(query2send,strlen(query2send)+strlen(mywhere)+1);
	/*STRNCAT*///strncat(query2send,mywhere,strlen(mywhere));
	query2send[q2slen]=' ';
	query2send[q2slen+1]='\0';
	//mystrncat(query2send,mywhere,strlen(mywhere));
	/*ADDED*/strncat(query2send,mywhere,strlen(mywhere));
	//strncat(query2send,"\0",1);
	/*DBG*/DEBUG == DBG_WHERE_HAN ? printf("Q2S_%s_\n",query2send) : 0;
	/*ADDED*/free(mywhere);
	if(theresavar==1){
		getchar();
	}
}

#ifdef _WIN32
static void idmp_query(VortexConnection *cn,VortexChannel *ch){
#else
void idmp_query(VortexConnection *cn,VortexChannel *ch){
#endif
	int msg_no;
	
	if(!vortex_channel_send_msg(ch,query2send,strlen(query2send),&msg_no)){
		perror("ERR - Unable to send messages\n");
		vortex_channel_close (ch,NULL);
		vortex_connection_close(cn);
		vortex_exit();
		exit(-1);
	}	
}

#ifdef _WIN32
static int results_handler(VortexChannel *ch,VortexConnection *cn,VortexAsyncQueue *queue,xmlDocPtr doc){
#else
int results_handler(VortexChannel *ch,VortexConnection *cn,VortexAsyncQueue *queue,xmlDocPtr doc){
#endif
	char *xpath,*content,xpath_ctrl[1024];
	char cntstr[HASH_INDEX_LENGHT];
	char *payload;
	int payload_len;
	int i=0,content_index,xpath_index;
	char index[HASH_INDEX_LENGHT];	
	xmlXPathContextPtr xpathCtx; 
    xmlXPathObjectPtr xpathObj;
    VortexFrame *frame;
    bool channel_ready,found=false;
	/*ADDED*/bool ans_num_received=false;
	/*ADDED*/int ans_num=-1,ans_counted=0;
	
	query_responses_cnt=0;
	channel_ready=true;
	//while(!((channel_ready || vortex_channel_is_ready(ch)) && (vortex_async_queue_length(queue)==0))){
	/*Il concetto è: finche non mi è arrivato l'ANS con il numero di ANS che mi aspetto, e finche non
	ho ricevuto tutte le ANS che mi aspetto, sto in waiting per i frame*/
	/*MODIF*/while((!ans_num_received) || (ans_counted < ans_num)){
		//channel_ready=false;
		frame=(VortexFrame *)vortex_channel_get_reply(ch,queue);
		if(frame!=NULL){
			//fprintf(stdout,"\b\b\b\b\b\b\b\b\b\b%010d",query_responses_cnt++);
			
			if(vortex_frame_get_payload_size(frame)>10){ /*E' arrivato un frame da leggere*/
				/*ADDED*/ans_counted++;
				/*DBG*/DEBUG == DBG_RESULT_HAN ? printf("DBG - (%d / %d)\n",ans_counted,ans_num) : 0;
						
				if(proceed==false){
					xpathCtx = xmlXPathNewContext(doc);
					if(xpathCtx != NULL){				
						sprintf(xpath_ctrl,"/signature/step[@num=%d]/@timeout",cur_sign->curstep+1);
						if((xpathObj = xmlXPathEvalExpression((xmlChar *)xpath_ctrl, xpathCtx))!= NULL){
							if(xpathObj->nodesetval!=NULL){
								if((int)xpathObj->nodesetval->nodeNr >0){
									/*DELETED*///cur_sign->curstep++;
									proceed=true;
								}
							}
						}else{
							fprintf(stderr,"Error: unable to evaluate xpath expression \n");  
						}
						xmlXPathFreeContext(xpathCtx);
					}else{
						fprintf(stderr,"Error: unable to create new XPath context\n"); 
					}	
				}
				payload_len=vortex_frame_get_payload_size(frame)+1;
				payload=(char *)calloc(sizeof(char),payload_len);
				/*DELETED*///snprintf(payload,payload_len,"%s",(char *)vortex_frame_get_payload(frame));
				/*ADDED*/strncpy(payload,(char *)vortex_frame_get_payload(frame),payload_len-1);
				i=12;
				//while(i<(payload_len-1)){
				/*MODIF*/while(i<(payload_len)){
					xpath_index=i;
					found=false;
					//while(i<(payload_len-1)&&!found){
					/*MODIF*/while(i<(payload_len)&&!found){
						//if(payload[i]!='\"'){
						/*MODIF*/if(payload[i]=='\"'){
							found=true;
						/*MODIF*/}else 
							i++;
					}
					xpath=(char *)calloc(sizeof(char),i-xpath_index+1);
					/*DELETED*///snprintf(xpath,i-xpath_index+1,"%s",&payload[xpath_index]);
					/*ADDED*/strncpy(xpath,&payload[xpath_index],i-xpath_index);
					i+=2;
					content_index=i;
					found=false;
					while(i<(payload_len-1)&&!found){
						//if(payload[i]!='<'){
						/*MODIF*/if(payload[i]=='<'){
							found=true;
						/*MODIF*/}else
						i++;
					}
					content=(char *)calloc(sizeof(char),i-content_index+1);
					/*DELETED*///snprintf(content,i-content_index+1,"%s",&payload[content_index]);
					/*ADDED*/strncpy(content,&payload[content_index],i-content_index);
					i+=7;
					sprintf(cntstr,"%d",xmlHashSize((xmlHashTable *)xmlHashLookup(result,(xmlChar *)xpath))+1);
					xmlHashAddEntry((xmlHashTable *)xmlHashLookup(result,(xmlChar *)xpath),(xmlChar *)cntstr,content);
					//~ xmlHash hold the pointer so can't deallocate strings
					//~ free(xpath);
					//~ free(content);
					i+=12;
				}
				/*ADDED*/free(payload);
				sprintf(index,"0");
				react_create(index,NULL,'d');
				/*DBG*/DEBUG == DBG_RESULT_HAN ? printf("DBG - esco dalla create\n") : 0;
				/*DBG*/DEBUG == DBG_HASH_RES ? xmlHashScan(result,HashItemPrint,NULL) : 0;
				/*DELETED*/xmlHashFree(result,hash_deallocate);
				/*ADDED*///xmlHashScan(result,hash_deallocate,NULL);
				/*ADDED*///xmlHashFree(result,hash_free);
				/*DBG*/DEBUG == DBG_HASH_RES ? printf("DBG - hash free result\n") : 0;
				/*MODIF*/result=xmlHashCreate(c0->max_hash_entry);
				/*DBG*/DEBUG == DBG_HASH_RES ? printf("DBG - ho ricreato la result\n") : 0;
				xmlHashScan(var,HashCreate,NULL);
				/*DBG*/DEBUG == DBG_HASH_VAR ? printf("DBG - ho fatto la hash scan var\n") : 0;
			/*MODIF*/}else if(vortex_frame_get_payload_size(frame)==10){// è arrivato il numero di ANS che mi dovrei aspettare
				/*ADDED*/sscanf(vortex_frame_get_payload(frame),"%10d",&ans_num);
				/*ADDED*/ans_num_received=true;
				/*DBG*/DEBUG == DBG_RESULT_HAN ? printf("DBG - ANS_NUM:%d\n",ans_num),getchar() : 0;
				//channel_ready=true;
			}
			/*DBG*/DEBUG == DBG_RESULT_HAN ? printf("DBG - prima di free frame\n") : 0;
			/*DELETED*///free(frame);
			/*ADDED*/vortex_frame_unref(frame);
			/*ADDED*///vortex_frame_free(frame);
			/*DBG*/DEBUG == DBG_RESULT_HAN ? printf("DBG - torno su\n") : 0;
			/*DBG*/DEBUG == DBG_RESULT_HAN ? printf("DBG - ready:%d | empty:%d\n",vortex_channel_is_ready(ch),vortex_async_queue_length(queue)) : 0;
		}	
	}
	/*DBG*/DEBUG == DBG_RESULT_HAN ? putchar('\n'), printf("END ANSW ARRIVED\n") : 0;
	
	if(proceed){					//if step performed && found another step
		cur_sign->curstep++;
		save_hp_sign(doc);
	}
	return ans_num;
}

#ifdef _WIN32
static void react_handler(char *react_str,int do_undo){
#else
void react_handler(char *react_str,int do_undo){
#endif
	char *varname,*tmp,cntstr[HASH_INDEX_LENGHT];
	int i,varlen,cnt=0,varindex;
	xmlHashTable *react;
	
	if(do_undo==PARSE_DO){
		react=react_do;
	}else if(do_undo==PARSE_UNDO){
		react=react_undo;
	}
	tmp=NULL;
	if(strstr(react_str,"$")==NULL){
		sprintf(cntstr,"%d",cnt++);
		xmlHashAddEntry(react,(xmlChar *)cntstr,react_str);
		/*DBG*/DEBUG == DBG_HASH_REAC ? printf("DBG - newreactentry (%d)(%s): _%s_\n",xmlHashSize(react),cntstr,react_str) : 0;
	}else{
		i=0;
		while(react_str[i]!='\0'){
			if(react_str[i]=='$'){
				if(tmp!=NULL){
					sprintf(cntstr,"%d",cnt++);
					xmlHashAddEntry(react,(xmlChar *)cntstr,tmp);
					/*DBG*/DEBUG == DBG_HASH_REAC ? printf("DBG - newreactentry (%d)(%s): _%s_\n",xmlHashSize(react),cntstr,tmp) : 0;
					//~ xmlHash hold the pointer so can't deallocate strings
					//~ free(tmp);
					tmp=NULL;
				}
				varlen=0;
				varindex=i;
				i++;
				while(((react_str[i]<='Z')&&(react_str[i]>='A'))||((react_str[i]<='9')&&(react_str[i]>='0'))||(react_str[i]=='_')){
					varlen++;
					i++;
				}
				varlen++;
				varname=(char *)calloc(sizeof(char),varlen+1);
				/*DELETED*///snprintf(varname,varlen+1,"%s",&react_str[varindex]);
				/*ADDED*/strncpy(varname,&react_str[varindex],varlen);
				sprintf(cntstr,"%d",cnt++);
				xmlHashAddEntry(react,(xmlChar *)cntstr,varname);
				/*DBG*/DEBUG == DBG_HASH_REAC ? printf("DBG - newreactentry (%d)(%s): _%s_\n",xmlHashSize(react),cntstr,varname) :0;
				i--;
				//~ xmlHash hold the pointer so can't deallocate strings
				//~ free(varname);
			}else{
				if(react_str[i]=='\\'){
					if(react_str[i+1]=='$'){
						i++;
					}	
				}
				if(tmp==NULL){
					tmp=(char *)calloc(sizeof(char),2);
				}else{
					tmp=(char *)realloc(tmp,strlen(tmp)+2);
				}
				strncat(tmp,&react_str[i],1);
				strncat(tmp,"\0",1);
			}
			i++;
		}
		if(tmp!=NULL){
			sprintf(cntstr,"%d",cnt++);
			xmlHashAddEntry(react,(xmlChar *)cntstr,tmp);
			/*DBG*/DEBUG == DBG_HASH_REAC ? printf("DBG - newreactentry (%d)(%s): _%s_\n",xmlHashSize(react),cntstr,tmp) : 0;
			//~ xmlHash hold the pointer so can't deallocate strings
			//~ free(tmp);
			tmp=NULL;	
		}
	}
}

#ifdef _WIN32
static void react_create(char *react_index,char *react_str,char t){
#else
void react_create(char *react_index,char *react_str,char t){
#endif
	int hash_size,dreact_index,i,react_dim=xmlHashSize((t=='d')?react_do:react_undo);
	char str_i[HASH_INDEX_LENGHT],react_index_to_pass[HASH_INDEX_LENGHT];
	xmlHashTablePtr hash,react=(t=='d')?react_do:react_undo;
	char *tmp,*tmp2;
	
	
	/*DBG*/DEBUG == DBG_REACT_CRE ? printf("DBG - chiamata alla create_react con %s %s %c\n",react_index,react_str,t) : 0;
	
	if(react_str==NULL){
		tmp=(char *)calloc(sizeof(char),strlen((char *)xmlHashLookup(react,(xmlChar *)react_index))+1);
		snprintf(tmp,strlen((char *)xmlHashLookup(react,(xmlChar *)react_index))+1,"%s",(char *)xmlHashLookup(react,(xmlChar *)react_index));
	}else{
		tmp=(char *)calloc(sizeof(char),strlen((char *)xmlHashLookup(react,(xmlChar *)react_index))+strlen(react_str)+1);
		snprintf(tmp,strlen((char *)xmlHashLookup(react,(xmlChar *)react_index))+strlen(react_str)+1,
					"%s%s",react_str,(char *)xmlHashLookup(react,(xmlChar *)react_index));
	}
	
	sscanf(react_index,"%d",&dreact_index);
	dreact_index++;
	sprintf(react_index,"%d",dreact_index);
	//if(dreact_index<react_dim){
	/*MODIF*/if(dreact_index<react_dim){
		hash=(xmlHashTablePtr)xmlHashLookup(result,(xmlChar *)xmlHashLookup(var,(xmlChar *)xmlHashLookup(react,(xmlChar *)react_index)));
		/*ADDED*/hash_size=xmlHashSize(hash);
		/*MODIF*///for(i=1;i<=xmlHashSize(hash);i++){
		for(i=1;i<=hash_size;i++){
			//snprintf(str_i,5,"%d",i);
			/*MODIF*/snprintf(str_i,HASH_INDEX_LENGHT,"%d",i);
			tmp2=(char *)calloc(sizeof(char),strlen(tmp)+strlen((char *)xmlHashLookup(hash,(xmlChar *)str_i))+1);
			snprintf(tmp2,strlen(tmp)+strlen((char *)xmlHashLookup(hash,(xmlChar *)str_i))+1,"%s%s",tmp,(char *)xmlHashLookup(hash,(xmlChar *)str_i));
			//snprintf(react_index_to_pass,5,"%d",dreact_index+1);
			/*MODIF*/snprintf(react_index_to_pass,HASH_INDEX_LENGHT,"%d",dreact_index+1);
			if(dreact_index+1<react_dim){
				react_create(react_index_to_pass,tmp2,t);
			}else{
				/*DBG*/DEBUG == DBG_REACT_CRE ? printf("DBG - salvo da qui perchè sono l'ultimo e la tabella finisce con una parte variabile\n") : 0;
				react_save(tmp2,t);
			}
			free(tmp2);
		}
	}else{
		/*DBG*/DEBUG == DBG_REACT_CRE ? printf("DBG - salvo da qui perchè sono l'ultimo e la tabella finisce con una parte fissa\n") : 0;
		react_save(tmp,t);
	}
	free(tmp);
	/*ADDED*/return;
}

#ifdef _WIN32
static void react_save(char *react,char t){
#else
void react_save(char *react,char t){
#endif
	char *save_filename,*send_filename;
	groups *cur;
	FILE *save_fp,*send_fp;
	char *on_fail=(t=='d')?cur_sign->react_do_on_fail:cur_sign->react_undo_on_fail;
	struct timeval tspc;
	/*ADDED*/#ifdef _WIN32
	/*ADDED*/win_gettimeofday(&tspc,NULL);
	/*ADDED*/#else
	gettimeofday(&tspc,NULL);
	/*ADDED*/#endif
	/*MODIF*/save_filename=(char *)calloc(sizeof(char),11+20+strlen(c0->dir_react));
	/*MODIF*/send_filename=(char *)calloc(sizeof(char),11+20+strlen(c0->dir_send));
	/*MODIF*/snprintf(save_filename,11+20+strlen(c0->dir_react),"%sreact_%010ld%010ld.xml",c0->dir_react,tspc.tv_sec,tspc.tv_usec);
	/*MODIF*/snprintf(send_filename,11+20+strlen(c0->dir_send),"%sreact_%010ld%010ld.xml",c0->dir_send,tspc.tv_sec,tspc.tv_usec);
	if((save_fp=fopen(save_filename,"w"))==NULL){
		fprintf(stderr,"ERR - Unable to open output file %s\n",save_filename);
		exit(-1);
	}
	if((send_fp=fopen(send_filename,"w"))==NULL){
		fprintf(stderr,"ERR - Unable to open output file %s\n",send_filename);
		exit(-1);
	}
	fprintf(save_fp,"<react origin=\"%s\" sig_id=\"%s\" step_num=\"%d\" undo_time=\"%d\">",cur_sign->origin,cur_sign->sig_id,cur_sign->curstep,cur_sign->undo_time);
	fprintf(send_fp,"<react origin=\"%s\" sig_id=\"%s\" step_num=\"%d\" undo_time=\"%d\">",cur_sign->origin,cur_sign->sig_id,cur_sign->curstep,cur_sign->undo_time);
	if(cur_sign->react_group_list!=NULL){
		fprintf(send_fp,"<groups>");
		fprintf(save_fp,"<groups>");
		for(cur=cur_sign->react_group_list;cur;cur=cur->next){
			fprintf(send_fp,"<group>%s</group>",cur->group_name);
			fprintf(save_fp,"<group>%s</group>",cur->group_name);
		}
		fprintf(send_fp,"</groups>");
		fprintf(save_fp,"</groups>");
	}
	fprintf(send_fp,"<do on_fail=\"%s\">%s</do></react>",on_fail,react);
	fprintf(save_fp,"<do on_fail=\"%s\">%s</do></react>",on_fail,react);
	fclose(send_fp);
	fclose(save_fp);
	free(send_filename);
	free(save_filename);
}

#ifdef _WIN32
static void save_hp_sign(xmlDocPtr doc){
#else
void save_hp_sign(xmlDocPtr doc){
#endif
	xmlNodePtr new_sign;
	char next_step[HASH_INDEX_LENGHT];
	char *hp_sign_name;
	struct timeval tspc;
	FILE *dump,*out;
	int found=0;
	char c;
	
	/*ADDED*/#ifdef _WIN32
	/*ADDED*/win_gettimeofday(&tspc,NULL);
	/*ADDED*/#else
	gettimeofday(&tspc,NULL);
	/*ADDED*/#endif
	/*MODIF*/hp_sign_name=(char *)calloc(sizeof(char),12+20+strlen(c0->dir_send));
	/*MODIF*/snprintf(hp_sign_name,12+20+strlen(c0->dir_send),"%shpsign_%010ld%010ld.xml",c0->dir_send,tspc.tv_sec,tspc.tv_usec);
	new_sign=xmlDocGetRootElement(doc);
	sprintf(next_step,"%d",cur_sign->curstep);
	xmlSetProp(new_sign,(xmlChar *)"cur_step",(xmlChar *)next_step);
	xmlSaveFile(hp_sign_name,doc);				
	dump=fopen(hp_sign_name,"rt");
	out=fopen("temp","wt");
	c=fgetc(dump);
	found=0;
	while(!feof(dump)){
		if(found<1){
			if(c=='>'){
				found++;	
				fgetc(dump);
			}
		}else{
			fputc(c,out);	
		}			
		c=fgetc(dump);									
	}
	fclose(dump);
	fclose(out);
	rename("temp",hp_sign_name);
	free(hp_sign_name);
}

#ifdef _WIN32
static void free_sign_struct(bool total){
#else
void free_sign_struct(bool total){
#endif
	groups *cur,*old;
	if(total==true){
		free(cur_sign->sig_id);
		cur_sign->sig_id=NULL;
		cur_sign->curstep=-1;
		cur_sign->timeout=0;
		cur_sign->undo_time=0;
	}
	free(cur_sign->on_timeout);
	cur_sign->on_timeout=NULL;
	free(cur_sign->severity);
	cur_sign->severity=NULL;
	free(cur_sign->query_string);
	cur_sign->query_string=NULL;
	free(cur_sign->origin);
	cur_sign->origin=NULL;
	free(cur_sign->react_do);
	cur_sign->react_do=NULL;
	free(cur_sign->react_do_on_fail);
	cur_sign->react_do_on_fail=NULL;
	free(cur_sign->react_undo);
	cur_sign->react_undo=NULL;
	free(cur_sign->react_undo_on_fail);
	cur_sign->react_undo_on_fail=NULL;
	old=NULL;
	for(cur=cur_sign->react_group_list;cur;cur=cur->next){
		if(old!=NULL){
			free(old->group_name);
			free(old);
		}
		old=cur;		
	}
	if(old!=NULL){
		free(old->group_name);
		free(old);
	}
	old=NULL;
	for(cur=cur_sign->detect_group_list;cur;cur=cur->next){
		if(old!=NULL){
			free(old->group_name);
			free(old);
		}
		old=cur;		
	}
	if(old!=NULL){
		free(old->group_name);
		free(old);
	}
	cur_sign->react_group_list=NULL;
	cur_sign->detect_group_list=NULL;
}

#ifdef _WIN32
static void free_structs(xmlDocPtr doc){
#else
void free_structs(xmlDocPtr doc){
#endif
	free_sign_struct(!proceed);
	/*DELETED*///if(proceed==false){
		/*DELETED*///free(doc);
	/*DELETED*///}
	free_hash_tables();
	/*DELETED*/xmlHashFree(result,hash_deallocate);
	/*ADDED*///xmlHashScan(result,hash_deallocate,NULL);
	/*ADDED*///xmlHashFree(result,hash_free);
	/*MODIF*/result=xmlHashCreate(c0->max_hash_entry);	
}

#ifdef _WIN32
static int timeout_start(sign *cs){
#else
int timeout_start(sign *cs){
#endif
	#ifdef _WIN32
	win_gettimeofday(&cs->timeout_start,NULL);
	#else
	gettimeofday(&cs->timeout_start,NULL);
	#endif
	return 1;
}

#ifdef _WIN32
static int timeout_handler(sign *cs){
#else
int timeout_handler(sign *cs){
#endif
	struct timeval now;
	long relative_sec;
	long relative_usec;
	int result;

	#ifdef _WIN32
	win_gettimeofday(&now,NULL);
	#else
	gettimeofday(&now,NULL);
	#endif

	relative_sec = ((long)((long)now.tv_sec - (long)cs->timeout_start.tv_sec) * (long)1000000);
	relative_usec = (relative_sec == 0LL) ? (long)((long)now.tv_usec - (long)cs->timeout_start.tv_usec) : 0LL;

	DBG_TIMEOUT == DEBUG ? printf("DBG - (%ld + %ld = %ld >< %ld)\n",relative_sec,relative_usec,(long)((long)relative_sec + (long)relative_usec),cs->timeout) : 0;

	return ((cs->timeout > 0) && ((long)cs->timeout >= (long)((long)relative_sec + (long)relative_usec))) ? 1 : 0;
}


#endif
